package com.hzz.framework.util;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;

@Slf4j
public class ByteConverterLittleUtil {

    /**
     * double转byte数组，小端模式
     *
     * @param d
     * @return
     */
    public static byte[] doubleToBytes_Little(double d) {
        long l = Double.doubleToLongBits(d);
        byte[] b = new byte[8];
        b[7] = (byte) (0xff & (l >> 56));
        b[6] = (byte) (0xff & (l >> 48));
        b[5] = (byte) (0xff & (l >> 40));
        b[4] = (byte) (0xff & (l >> 32));
        b[3] = (byte) (0xff & (l >> 24));
        b[2] = (byte) (0xff & (l >> 16));
        b[1] = (byte) (0xff & (l >> 8));
        b[0] = (byte) (0xff & l);
        return b;
    }

    /**
     * byte数组转double
     *
     * @param bytes        8位byte数组
     * @param littleEndian 是否是小端模式
     * @return
     */
    public static double bytesToDouble_Little(byte[] bytes, boolean littleEndian) {
        ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, 8);
        if (littleEndian) {
            // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN)
            // ByteBuffer 默认为大端(BIG_ENDIAN)模式
            buffer.order(ByteOrder.LITTLE_ENDIAN);
        }
        long l = buffer.getLong();
        return Double.longBitsToDouble(l);
    }

    /**
     * long转byte数组，小端模式
     *
     * @param l
     * @return
     */
    public static byte[] longToBytes_Little(long l) {
        byte[] b = new byte[8];
        b[7] = (byte) (0xff & (l >> 56));
        b[6] = (byte) (0xff & (l >> 48));
        b[5] = (byte) (0xff & (l >> 40));
        b[4] = (byte) (0xff & (l >> 32));
        b[3] = (byte) (0xff & (l >> 24));
        b[2] = (byte) (0xff & (l >> 16));
        b[1] = (byte) (0xff & (l >> 8));
        b[0] = (byte) (0xff & l);
        return b;
    }

    /**
     * byte数组转long
     *
     * @param bytes 8位的byte数组
     * @return
     * @throws Exception
     */
    public static long bytesToLong_Little(byte[] bytes) throws Exception {
        return bytesToLong_Little(bytes, true);
    }

    /**
     * byte数组转long
     *
     * @param bytes        8位的byte数组
     * @param littleEndian 是否是小端模式
     * @return
     * @throws Exception
     */
    public static long bytesToLong_Little(byte[] bytes, boolean littleEndian) throws Exception {
        if (bytes.length != 8) {
            throw new Exception("参数错误，无法解析。");
        }
        ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, 8);
        if (littleEndian) {
            // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN)
            // ByteBuffer 默认为大端(BIG_ENDIAN)模式
            buffer.order(ByteOrder.LITTLE_ENDIAN);
        }
        return buffer.getLong();
    }

    /**
     * int转byte数组  ,小端
     *
     * @param num
     * @return
     */
    public static byte[] intToBytes_Little(int num) {
        byte[] result = new byte[4];
        result[0] = (byte) ((num >>> 0) & 0xff);
        result[1] = (byte) ((num >>> 8) & 0xff);
        result[2] = (byte) ((num >>> 16) & 0xff);
        result[3] = (byte) ((num >>> 24) & 0xff);
        return result;
    }

    /**
     * byte数组转int,小端
     *
     * @param bytes
     * @return
     */
    public static int bytesToInt_Little(byte[] bytes) {
        int result = 0;
        if (bytes.length == 4) {
            int a = (bytes[0] & 0xff) << 0;
            int b = (bytes[1] & 0xff) << 8;
            int c = (bytes[2] & 0xff) << 16;
            int d = (bytes[3] & 0xff) << 24;
            result = a | b | c | d;
        }
        return result;
    }

    /**
     * byte数组转十六进制
     *
     * @param bytes
     * @return
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder buf = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) { // 使用String的format方法进行转换
            buf.append(String.format("%02x ", new Integer(b & 0xff)));
        }

        return buf.toString();
    }

    /**
     * 十六进制转byte数组
     *
     * @param str
     * @return
     */
    public static byte[] hexToBytes(String str) {
        if (str == null || "".equals(str.trim())) {
            return new byte[0];
        }
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() / 2; i++) {
            String subStr = str.substring(i * 2, i * 2 + 2);
            bytes[i] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    public static int byte2int_Little(byte[] b) {
        if (b.length < 4) {
            byte[] bytes = {0, 0, 0, 0};
            System.arraycopy(b, 0, bytes, bytes.length - b.length, b.length);
            b = bytes;
        }
        return b[0] & 0xFF |
                (b[1] & 0xFF) << 8 |
                (b[2] & 0xFF) << 16 |
                (b[3] & 0xFF) << 24;
    }

    /**
     * int转byte数组
     */
    public static byte[] int2byte_Little(int num) {
        byte[] bytes = new byte[4];
        bytes[3] = (byte) ((num >> 24) & 0xff);
        bytes[2] = (byte) ((num >> 16) & 0xff);
        bytes[1] = (byte) ((num >> 8) & 0xff);
        bytes[0] = (byte) (num & 0xff);
        return bytes;
    }

    public static float byte2float_Little(byte[] b) {
        ByteBuffer buffer = ByteBuffer.wrap(b, 0, 4);
        // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN)
        // ByteBuffer 默认为大端(BIG_ENDIAN)模式
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        int l = buffer.getInt();
        return Float.intBitsToFloat(l);
    }

    public static byte[] float2byte_Little(float f) {
        long l = Float.floatToIntBits(f);
        byte[] b = new byte[4];
        b[3] = (byte) (0xff & (l >> 24));
        b[2] = (byte) (0xff & (l >> 16));
        b[1] = (byte) (0xff & (l >> 8));
        b[0] = (byte) (0xff & l);
        return b;
    }

    public static byte[] char2byte_Little(char c) {
        byte[] b = new byte[2];
        b[1] = (byte) ((c & 0xFF00) >> 8);    //0xff00=1111 1111 0000 0000
        b[0] = (byte) (c & 0xFF);   //0xff,=1111 1111
        return b;
    }

    public static char byte2char_Little(byte[] b) {
        char c = 0;
        if (b.length == 1) {
            c = (char) (b[0] & 0xFF);
        } else {
            c = (char) (((b[1] & 0xFF) << 8) | (b[0] & 0xFF));
        }
        return c;
    }

    public static byte[] short2byte_Little(short s) {
        byte[] b = new byte[2];
        b[1] = (byte) ((s >> 8) & 0xff);
        b[0] = (byte) ((s) & 0xff);
        return b;
    }

    public static int byte2short_Little(byte[] b) {
        return ((short) (b[0] & 0xff)) + ((short) (b[1] & 0xff) << 8);
    }

    public static byte[] string2byte_Little(String str) {
        if (str == null) {
            return null;
        }
        byte[] byteArray = str.getBytes();
        return byteArray;
    }

    public static String byte2string_Little(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        String str = new String(bytes);
        if (ValidatorUtil.notEmpty(str)) {
            str = str.trim().replaceAll("[\u0000-\u001f\b]", "");
        }
        return str;
    }

    public static byte[] unicode2byte_Little(String s) {
        byte[] abyte = null;
        try {
            abyte = s.getBytes(StandardCharsets.UTF_16LE);
        } catch (Exception e) {
            log.error("转码错误!", e);
        }
        return abyte;
    }

    public static String byte2unicode_Little(byte[] src) {
        String s = null;
        try {
            s = new String(src, StandardCharsets.UTF_16LE);
            if (ValidatorUtil.notEmpty(s)) {
                return s.trim().replaceAll("[\u0000-\u001f\b]", "");
            }
        } catch (Exception e) {
            log.error("转码错误!", e);
        }
        return s;
    }

    public static int byte2UnsignedShort_Little(byte[] bytes) {
        int low = bytes[0];
        int high = bytes[1];
        return (high << 8 & 0xFF00) | (low & 0xFF);
    }


    public static byte[] unsignedShort2Byte_Little(int s) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (s & 0xFF);
        bytes[1] = (byte) (s >> 8 & 0xFF);
        return bytes;
    }


    public static void main(String[] args) throws IOException {
        for (byte b : int2byte_Little(1)) {
            System.out.println(b);
        }
    }
}
